home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
User's Choice Windows CD
/
User's Choice Windows CD (CMS Software)(1993).iso
/
misc1
/
iv26_w30.zip
/
SOURCES
/
WBITMAP.C
< prev
next >
Wrap
C/C++ Source or Header
|
1980-01-22
|
16KB
|
601 lines
/*
* MS - dependent bitmap code
*/
#include <Interviews\bitmap.h>
#include <Interviews\font.h>
#include <Interviews\transformer.h>
#include <Interviews\X11\painterrep.h>
#include <Interviews\X11\worldrep.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
#include <dir.h>
#include <fstream.h>
static int BitmapSize (unsigned int w, unsigned int h) {
return (w+7)/8 * h;
}
int hextoi (char* s) {
int result;
sscanf(s, "%x", &result);
return result;
}
/*
* Steps through an X Bitmap File and collects extracted values in an
* array.
*/
int BitmapRep::ParseBitmapFile (const char* filename, char** data) {
ifstream source;
char* file;
if ((file = searchpath(filename)) == NULL) {
return 0;
}
source.open(file, ios::nocreate);
if (!source) {
int a;
a = 1;
} else {
char buf[256];
char* ptr;
source.getline(buf, 256);
if ((ptr = strstr(buf, "width")) != NULL) {
ptr = strpbrk(ptr, "0123456789");
width = atoi(ptr);
}
source.getline(buf, 256);
if ((ptr = strstr(buf, "height")) != NULL) {
ptr = strpbrk(ptr, "0123456789");
height = atoi(ptr);
}
source.getline(buf, 256);
if ((ptr = strstr(buf, "x_hot")) != NULL) {
ptr = strpbrk(ptr, "0123456789");
x0 = atoi(ptr);
source.getline(buf, 256);
}
if ((ptr = strstr(buf, "y_hot")) != NULL) {
ptr = strpbrk(ptr, "0123456789");
y0 = atoi(ptr);
source.getline(buf, 256);
}
int size = BitmapSize(width, height);
char* d = new char[size];
int index = 0;
do {
ptr = buf;
while ((ptr = strstr(ptr, "0x")) != NULL) {
d[index++] = hextoi(ptr);
ptr++;
}
source.getline(buf, 256);
} while (!source.eof());
*data = d;
return 1;
}
}
int BitmapDataSize (int width, int height) {
return ((width/16 + 1)*height);
}
/*
* A data byte of an X Bitmap must be reflected to get the Windows Format.
*/
unsigned BitmapRep::ReflectByte (unsigned value) {
unsigned sbit, dbit, result = 0;
for (int i = 0; i < 8; i++) {
sbit = 1 << i;
dbit = 128 >> i;
if (sbit & value) {
result += dbit;
}
}
return result;
}
/*
* Organizes an incoming data array to Windows Format. The width and height
* of a Windows Bitmap are always multiples of 16. X organizes his bitmaps
* as a continous byte stream. 2 byte units must be created.
*/
void BitmapRep::CreateWinFormat (char* data, unsigned** newdata) {
int column, row = 0;
int j = 0, i = 0;
boolean high;
unsigned value;
unsigned* d = new unsigned[BitmapDataSize(width, height)];
while (row < height) {
column = 0;
high = false;
while (column < width) {
column += 8;
value = ReflectByte(data[i]);
i++;
if (high) {
d[j] += value << 8;
high = false;
j++;
} else {
d[j] = value;
high = true;
}
}
if (high) {
j++;
}
row++;
}
*newdata = d;
}
boolean BitmapRep::IsWinFormat (const char* filename) {
if (strstr(filename, ".bmp")) {
return true;
}
return false;
}
/*
* Returns width, height of the bitmap.
*/
void BitmapRep::GetBitmapExt () {
HDC hMemDC = CreateCompatibleDC(NULL);
HBITMAP holdBitmap = SelectObject(hMemDC, (HBITMAP)map);
RECT rect;
GetClipBox(hMemDC, &rect);
width = rect.right;
height = rect.bottom;
SelectObject(hMemDC, holdBitmap);
DeleteDC(hMemDC);
}
BitmapRep::BitmapRep (const char* filename) {
if (IsWinFormat(filename)) {
map = (void*)LoadBitmap(_world->hinstance(), (LPSTR)filename);
GetBitmapExt();
} else {
char* data;
unsigned* windata;
ParseBitmapFile(filename, &data);
CreateWinFormat(data, &windata);
map = (void*)CreateBitmap (width, height, 1, 1, (LPSTR)windata);
delete data;
delete windata;
data = nil;
}
data = nil;
}
BitmapRep::BitmapRep (
char* d, unsigned int w, unsigned int h, int x, int y
) {
unsigned* newd;
width = w; height = h;
x0 = x; y0 = y;
CreateWinFormat(d, &newd);
map = (void*)CreateBitmap (w, h, 1, 1, (LPSTR)newd);
delete newd;
data = nil;
}
BitmapRep::BitmapRep (Font* f, int c) {
HDC hMemDC = CreateCompatibleDC(NULL);
if (!f->Valid()) {
return;
}
HFONT holdFont = SelectObject(hMemDC, (HFONT)f->Id());
width = GetTextExtent(hMemDC, (char*)&c, 1);
height = f->Height();
x0 = 0; y0 = 0;
map = (void*)CreateBitmap (width, height, 1, 1, NULL);
HBITMAP holdBitmap = SelectObject(hMemDC, (HBITMAP)map);
TextOut(hMemDC, 0, 0, (LPSTR)&c, 1);
SelectObject(hMemDC, holdFont);
SelectObject(hMemDC, holdBitmap);
DeleteDC(hMemDC);
data = nil;
}
BitmapRep::BitmapRep (BitmapRep* b, BitTx t) {
switch (t) {
case NoTx: case FlipH: case FlipV: case Rot180: case Inv:
width = b->width; height = b->height; break;
case Rot90: case Rot270:
width = b->height; height = b->width; break;
}
x0 = b->x0;
y0 = b->y0;
map = (void*)CreateBitmap(width, height, 1, 1, NULL);
for (int x = 0; x < width; ++x) {
for (int y = 0; y < height; ++y) {
boolean bit;
switch(t) {
case NoTx: bit = b->GetBit(x, y); break;
case FlipH: bit = b->GetBit(width-x-1, y); break;
case FlipV: bit = b->GetBit(x, height-y-1); break;
case Rot90: bit = b->GetBit(height-y-1, x); break;
case Rot180: bit = b->GetBit(width-x-1, height-y-1); break;
case Rot270: bit = b->GetBit(y, width-x-1); break;
case Inv: bit = !b->GetBit(x, y); break;
}
PutBit(x, y, bit);
}
}
}
/*----------------------------------------------------------------------*/
static void DrawSourceTransformedImage (
HBITMAP s, int sx0, int sy0,
HBITMAP m, int mx0, int my0,
HWND d, unsigned int height, int dx0, int dy0,
boolean stencil, COLORREF fg, COLORREF bg,
HDC hDC, Transformer* matrix,
int xmin, int ymin, int xmax, int ymax,
int s_width, int s_height,
int m_width, int m_height
) {
HDC hmDC = CreateCompatibleDC(hDC);
HDC hsDC = CreateCompatibleDC(hDC);
HBITMAP holdBitmap_s = SelectObject(hsDC, s);
HBITMAP holdBitmap_m = SelectObject(hmDC, m);
COLORREF lastdrawnpixel = fg;
for (int xx = xmin; xx <= xmax; ++xx) {
float lx, ly;
float rx, ry;
float tx, ty;
matrix->Transform(float(xx), float(ymin), lx, ly);
matrix->Transform(float(xx + 1), float(ymin), rx, ry);
matrix->Transform(float(xx), float(ymax+1), tx, ty);
float dx = (tx - lx) / float(ymax - ymin + 1);
float dy = (ty - ly) / float(ymax - ymin + 1);
int ilx = 0, ily = 0;
int irx = 0, iry = 0;
boolean lastmask = false, mask;
COLORREF lastpixel = fg, pixel, source;
for (int yy = ymin; yy <= ymax+1; ++yy) {
mask = (
(yy <= ymax)
&& (m == nil || GetPixel(hmDC, xx-mx0, m_height-1-(yy-my0) != -1))
);
if (
yy<sy0 || yy>=sy0+s_height || xx<sx0 || xx>=sx0+s_width
) {
source = bg;
} else {
DWORD rgb = GetPixel(hsDC, xx-sx0, s_height-1-(yy-sy0));
source = PALETTERGB(GetRValue(rgb), GetGValue(rgb), GetBValue(rgb));
}
if (stencil) {
pixel = (source != 0x2000000) ? fg : bg;
} else {
pixel = source;
}
if (mask != lastmask || lastmask && pixel != lastpixel) {
int iilx = round(lx), iily = round(ly);
int iirx = round(rx), iiry = round(ry);
if (lastmask) {
if (lastpixel != lastdrawnpixel) {
SetTextColor(hDC, lastpixel);
lastdrawnpixel = lastpixel;
}
if (
(ilx==iilx || ily==iily) && (irx==ilx || iry==ily)
) {
HBRUSH hBrush = CreateSolidBrush(lastpixel);
RECT rect;
rect.left = min(ilx, iirx) - dx0;
rect.top = height - (max(ily, iiry) - dy0);
rect.right = rect.left + abs(ilx - iirx);
rect.bottom = rect.top + abs(ily - iiry);
::FillRect(hDC, &rect, hBrush);
DeleteObject(hBrush);
} else {
POINT v[4];
v[0].x = ilx-dx0; v[0].y = height - (ily-dy0);
v[1].x = iilx-dx0; v[1].y = height - (iily-dy0);
v[2].x = iirx-dx0; v[2].y = height - (iiry-dy0);
v[3].x = irx-dx0; v[3].y = height - (iry-dy0);
HBRUSH hBrush = CreateSolidBrush(lastpixel);
HPEN hPen = GetStockObject(NULL_PEN);
HBRUSH holdBrush = SelectObject(hDC, hBrush);
HPEN holdPen = SelectObject(hDC, hPen);
::Polygon(hDC, v, 4);
SelectObject(hDC, holdPen);
SelectObject(hDC, holdBrush);
DeleteObject(hBrush);
}
}
ilx = iilx; ily = iily;
irx = iirx; iry = iiry;
lastpixel = pixel;
lastmask = mask;
}
lx += dx; ly += dy;
rx += dx; ry += dy;
}
}
SetTextColor(hDC, fg);
SelectObject(hsDC, holdBitmap_s);
SelectObject(hmDC, holdBitmap_m);
DeleteDC(hsDC);
DeleteDC(hmDC);
}
static void DrawDestinationTransformedImage (
HBITMAP s, int sx0, int sy0,
HBITMAP m, int mx0, int my0,
HWND d, unsigned int height, int dx0, int dy0,
boolean stencil, COLORREF fg, COLORREF bg,
HDC hDC, Transformer* matrix,
int xmin, int ymin, int xmax, int ymax,
int s_width, int s_height,
int m_width, int m_height
) {
HBRUSH holdBrush;
HDC hmDC = CreateCompatibleDC(hDC);
HDC hsDC = CreateCompatibleDC(hDC);
HBITMAP holdBitmap_m = SelectObject(hmDC, m);
HBITMAP holdBitmap_s = SelectObject(hsDC, s);
Transformer t(matrix);
t.Invert();
COLORREF lastdrawnpixel = fg;
for (Coord xx = xmin; xx <= xmax; ++xx) {
float fx, fy;
float tx, ty;
t.Transform(float(xx) + 0.5, float(ymin) + 0.5, fx, fy);
t.Transform(float(xx) + 0.5, float(ymax) + 1.5, tx, ty);
float dx = (tx - fx) / float(ymax - ymin + 1);
float dy = (ty - fy) / float(ymax - ymin + 1);
Coord lasty = ymin;
boolean lastmask = false, mask;
COLORREF lastpixel = fg, pixel, source;
for (Coord yy = ymin; yy <= ymax+1; ++yy) {
int ix = round(fx - 0.5), iy = round(fy - 0.5);
boolean insource = (
ix >= sx0 && ix < sx0 + s_width
&& iy >= sy0 && iy < sy0 + s_height
);
boolean inmask = (
m != nil && ix >= mx0 && ix < mx0 + m_width
&& iy >= my0 && iy < my0 + m_height
);
if (yy <= ymax) {
if (m == nil) {
mask = insource;
} else if (inmask) {
mask = GetPixel(hmDC, ix-mx0, m_height-1-(iy-my0)) != -1;
} else {
mask = false;
}
} else {
mask = false;
}
if (insource) {
DWORD rgb = GetPixel(hsDC, ix-sx0, s_height-1-(iy-sy0));
source = PALETTERGB(GetRValue(rgb), GetGValue(rgb), GetBValue(rgb));
} else {
source = bg;
}
if (stencil) {
pixel = (source != 0x2000000) ? fg : bg;
} else {
pixel = source;
}
if (mask != lastmask || lastmask && pixel != lastpixel) {
if (lastmask) {
if (lastpixel != lastdrawnpixel) {
SetTextColor(hDC, lastpixel);
lastdrawnpixel = lastpixel;
}
HBRUSH hBrush = CreateSolidBrush(lastpixel);
RECT rect;
rect.left = xx - dx0;
rect.top = height -1 -(yy -dy0);
rect.right = rect.left + 1;
rect.bottom = rect.top + (yy - lasty);
FillRect(hDC, &rect, hBrush);
DeleteObject(hBrush);
}
lastmask = mask;
lastpixel = pixel;
lasty = yy;
}
fx += dx;
fy += dy;
}
}
SetTextColor(hDC, fg);
SelectObject(hsDC, holdBitmap_s);
SelectObject(hmDC, holdBitmap_m);
DeleteDC(hsDC);
DeleteDC(hmDC);
}
void DrawTransformedImage (
HBITMAP s, int sx0, int sy0,
HBITMAP m, int mx0, int my0,
HWND d, unsigned int height, int dx0, int dy0,
boolean stencil, COLORREF fg, COLORREF bg,
HDC hDC, Transformer* matrix,
int s_width, int s_height,
int m_width, int m_height
) {
int x1 = (m != nil) ? mx0 : sx0;
int y1 = (m != nil) ? my0 : sy0;
int x2 = (m != nil) ? mx0 : sx0;
int y2 = (m != nil) ? my0 + m_height : sy0 + s_height;
int x3 = (m != nil) ? mx0 + m_width : sx0 + s_width;
int y3 = (m != nil) ? my0 + m_height : sy0 + s_height;
int x4 = (m != nil) ? mx0 + m_width : sx0 + s_width;
int y4 = (m != nil) ? my0 : sy0;
int sxmin = min(x1, min(x2, min(x3, x4)));
int sxmax = max(x1, max(x2, max(x3, x4))) - 1;
int symin = min(y1, min(y2, min(y3, y4)));
int symax = max(y1, max(y2, max(y3, y4))) - 1;
matrix->Transform(x1, y1);
matrix->Transform(x2, y2);
matrix->Transform(x3, y3);
matrix->Transform(x4, y4);
int dxmin = min(x1,min(x2,min(x3,x4)));
int dxmax = max(x1,max(x2,max(x3,x4))) - 1;
int dymin = min(y1,min(y2,min(y3,y4)));
int dymax = max(y1,max(y2,max(y3,y4))) - 1;
int swidth = sxmax - sxmin + 1;
int sheight = symax - symin + 1;
int dwidth = dxmax - dxmin + 1;
int dheight = dymax - dymin + 1;
boolean rect = (x1==x2 || y1==y2) && (x1==x4 || y1==y4);
boolean alwaysdest = dwidth < 2 * swidth;
boolean alwayssource = dwidth * dheight > 3 * swidth * sheight;
boolean dest;
dest = alwaysdest || (!alwayssource && !rect);
if (dest) {
if (dheight > 0) {
DrawDestinationTransformedImage(
s, sx0, sy0, m, mx0, my0, d, height, dx0, dy0,
stencil, fg, bg, hDC, matrix,
dxmin, dymin, dxmax, dymax,
s_width, s_height,
m_width, m_height
);
}
} else {
if (sheight > 0) {
DrawSourceTransformedImage(
s, sx0, sy0, m, mx0, my0, d, height, dx0, dy0,
stencil, fg, bg, hDC, matrix,
sxmin, symin, sxmax, symax,
s_width, s_height,
m_width, m_height
);
}
}
}
BitmapRep::BitmapRep (BitmapRep* b, Transformer* matrix) {
Transformer t(matrix);
Coord x1 = - b->x0;
Coord y1 = - b->y0;
Coord x2 = - b->x0;
Coord y2 = b->height - b->y0;
Coord x3 = b->width - b->x0;
Coord y3 = b->height - b->y0;
Coord x4 = b->width - b->x0;
Coord y4 = - b->y0;
t.Transform(x1, y1);
t.Transform(x2, y2);
t.Transform(x3, y3);
t.Transform(x4, y4);
Coord xmax = max(x1,max(x2,max(x3,x4))) - 1;
Coord xmin = min(x1,min(x2,min(x3,x4)));
Coord ymax = max(y1,max(y2,max(y3,y4))) - 1;
Coord ymin = min(y1,min(y2,min(y3,y4)));
int w = xmax - xmin + 1;
int h = ymax - ymin + 1;
width = (w <= 0) ? 1 : w;
height = (h <= 0) ? 1 : h;
x0 = -xmin;
y0 = -ymin;
HDC hMemDC = CreateCompatibleDC(NULL);
map = (void*)CreateBitmap(width, height, 1, 1, NULL);
HBITMAP holdBitmap = SelectObject(hMemDC, (HBITMAP)map);
PatBlt(hMemDC, 0, 0, width, height, WHITENESS);
DrawTransformedImage(
(HBITMAP)b->GetData(), -b->x0, -b->y0,
(HBITMAP)b->GetData(), -b->x0, -b->y0,
(HBITMAP)map, height, -x0, -y0,
true, 1, 0, hMemDC, &t,
b->width, b->height,
b->width, b->height
);
SelectObject(hMemDC, holdBitmap);
DeleteDC (hMemDC);
data = nil;
}
BitmapRep::~BitmapRep () {
Touch();
}
void BitmapRep::Touch () {
/* if (map != nil) {
DeleteObject((HBITMAP)map);
map = nil;
}
*/
}
void BitmapRep::PutBit (int x, int y, boolean bit) {
HDC hMemDC = CreateCompatibleDC(NULL);
HBITMAP holdBitmap = SelectObject(hMemDC, (HBITMAP)map);
if (bit) {
SetPixel(hMemDC, x, y, RGB(255, 255, 255));
} else {
SetPixel(hMemDC, x, y, RGB(0, 0, 0));
}
SelectObject(hMemDC, holdBitmap);
DeleteDC(hMemDC);
}
boolean BitmapRep::GetBit (int x, int y) {
boolean result;
HDC hMemDC = CreateCompatibleDC(NULL);
HBITMAP holdBitmap = SelectObject(hMemDC, (HBITMAP)map);
if (GetPixel(hMemDC, x, y) != 0xFFFFFF) {
result = false;
} else {
result = true;
}
SelectObject(hMemDC, holdBitmap);
DeleteDC(hMemDC);
return result;
}
void* BitmapRep::GetData () {
return map;
}
void* BitmapRep::GetMap () {
return map;
}